﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ColorClusteringSOM.Util
{

    class Point
    {
        private int x = 0;
        private int y = 0;

        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public int X { set { this.x = value; } get { return this.x; } }
        public int Y { set { this.y = value; } get { return this.y; } }
    }
    /// <summary>
    /// Trida pro generovani vystupu pro fidlera
    /// </summary>
    class Fidler
    {


        private Network network;
        private int rows;
        private int cols;

        public int Cols
        {
            get { return cols; }

        }


        public int Rows
        {
            get { return rows; }

        }


        public Network Network
        {
            get { return network; }
            set
            {
                network = value;
                rows = network.Rows;
                cols = network.Cols;
            }
        }


        public void FidlerOutput(Network network, String nameFile)
        {
            Neuron neuron = null;
            String output = String.Empty;
            Network = network;

            for (int i = 0; i < Rows; i++)
            {
                for (int j = 0; j < Cols; j++)
                {
                    neuron = network[i, j];

                    output += Distances2(neuron);

                    // zapsat 

                }
            }

            output = output.Replace(',', '.');

            Writer.WriteFidler(output, nameFile);

        }

        

        /// <summary>
        /// Pro vypocet ctverce kolem neuronu a pote se projdou vsechny neurony ve ctverci 
        /// ke kterym se vypocita vzdalenosti. 
        /// </summary>
        /// <param name="neuron"></param>
        /// <returns>Vrati string se vzdalenostmi</returns>
        private String Distances(Neuron centr)
        {
            Neuron neuron = null;
            String s = String.Empty;

            int nX = centr.X;
            int nY = centr.Y;


            Point left = new Point(nX, nY - 1);
            Point right = new Point(nX, nY + 1);
            Point up = new Point(nX - 1, nY);
            Point down = new Point(nX + 1, nY);

            double distance = 0.0;

            try
            {
                neuron = network[left.X, left.Y];
                distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron, centr);
                distance = 1 - distance;
                Console.WriteLine(distance);
                s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
                s += "\n";
            }
            catch (NullReferenceException)
            {

                //Console.WriteLine("NullReferenceException");
            }
            catch (IndexOutOfRangeException)
            {

                //Console.WriteLine("IndexOutOfRangeException");
            }
            try
            {
                //Console.WriteLine(distance);
 
                neuron = network[right.X, right.Y];
                distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron, centr);
                distance = 1 - distance;
                Console.WriteLine(distance);
 
                s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
                s += "\n";
            }
            catch (NullReferenceException)
            {

               // Console.WriteLine("NullReferenceException");
            }
            catch (IndexOutOfRangeException)
            {

                //Console.WriteLine("IndexOutOfRangeException");
            }

            try
            {
                //Console.WriteLine(distance);
 
                neuron = network[up.X, up.Y];
                distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron, centr);
                distance = 1 - distance;
                Console.WriteLine(distance);
 
                s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
                s += "\n";

            }
            catch (NullReferenceException)
            {

                //Console.WriteLine("NullReferenceException");
            }
            catch (IndexOutOfRangeException)
            {

                //Console.WriteLine("IndexOutOfRangeException");
            }
            try
            {
                neuron = network[down.X, down.Y];
                distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron, centr);
               distance = 1 - distance;

                s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
                s += "\n";

            }
            catch (NullReferenceException)
            {

                //Console.WriteLine("NullReferenceException");
            }
            catch (IndexOutOfRangeException)
            {

                //Console.WriteLine("IndexOutOfRangeException");
            }



            //******* PRO CELE OKOLI
            //int startX = nX - 1;
            //int startY = nY - 1;

            //int endX = nX + 1;
            //int endY = nY + 1;

            //if (startX <= 0)
            //{
            //    startX = 0;
            //}
            //if (startY <= 0)
            //{
            //    startY = 0;
            //}
            //if (endX >= (cols-1))
            //{
            //    endX = cols - 1;
            //}
            //if (endY >= (rows-1))
            //{
            //    endY = rows-1;
            //}

            //for (int i = startX; i <= endX; i++)
            //{

            //    for (int j = startY; j <= endY; j++)
            //    {
            //        if (i == startX && j == startY || i == startX && j == endY || i == endX && j == startY || i == endX && j == endY)
            //        {
            //            continue;
            //        }

            //        neuron = network[i,j];
            //        double distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron,centr);
            //        distance = 1- distance;


            //        if (neuron.Equals(centr))
            //        {

            //            continue; // vzdalenost by byla 0 protoze by neuron pocital vzdalenost ke svemu samemu
            //        }


            //        s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
            //        s += "\n";

            //    }

            //}

            return s;

        }


        private String Distances2(Neuron centr)
        {
            Neuron neuron = null;
            String s = String.Empty;

            int nX = centr.X;
            int nY = centr.Y;

            int cols = network.Cols -1;
            int rows = network.Rows -1;

                      


            Point left = new Point(nX, nY - 1);
            if(left.Y < 0)
                left.Y = 0;
            
            Point right = new Point(nX, nY + 1);
            if (right.Y > cols)
                right.Y = cols;
            
            Point up = new Point(nX - 1, nY);
            if (up.X < 0)
                up.X = 0;

            Point down = new Point(nX + 1, nY);
            if (down.X > rows)
                down.X = rows;

            Point[] po = {left,right,up,down};


            double maxDistance = Double.MinValue;

            for (int i = 0; i <= 3; i++)
            {
                double pom;
                Neuron pomNeu = network[po[i].X,po[i].Y];

                if (pomNeu.NumberOfNeuron == centr.NumberOfNeuron)
                    continue;
                

                pom = Helper.EuklidDistanceBetweenNormalNeurons(pomNeu, centr);

                if (maxDistance < pom)
                {
                    maxDistance = pom;
                }
            
            }



            double distance = 0.0;

            
                neuron = network[left.X, left.Y];
                if (neuron.NumberOfNeuron != centr.NumberOfNeuron)
                {
                    distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron, centr);
                    distance = 1 - (distance/maxDistance);
                    //Console.WriteLine(distance);
                    s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
                    s += "\n";
                }

                neuron = network[right.X, right.Y];
                if (neuron.NumberOfNeuron != centr.NumberOfNeuron)
                {
                    distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron, centr);
                    distance = 1 - (distance / maxDistance);
                    //Console.WriteLine(distance);

                    s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
                    s += "\n";
                }
                
                neuron = network[up.X, up.Y];
                if (neuron.NumberOfNeuron != centr.NumberOfNeuron)
                {
                    distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron, centr);
                    distance = 1 - (distance / maxDistance);
                    //Console.WriteLine(distance);

                    s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
                    s += "\n";
                }
           

                neuron = network[down.X, down.Y];
                if (neuron.NumberOfNeuron != centr.NumberOfNeuron)
                {
                    distance = Helper.EuklidDistanceBetweenNormalNeurons(neuron, centr);
                    distance = 1 - (distance / maxDistance);

                    s += centr.NumberOfNeuron + " " + neuron.NumberOfNeuron + " " + distance;
                    s += "\n";

                }
            return s;

        }



    }

}
